import * as THREE from "three"
import vjmap3d, { animationAsync, App, interpolatePointsByRatio, PathTubeEntities, SpriteMarkerEntity, toVector3 } from "vjmap3d"
import { env } from "./env";
import { mockData } from "./mock";
import { createShaderWave, createWavePoint } from "./util";
export const loadSceneData = async (app: App) => {

    let texture = app.getLoadedResources().getTexture("outerwall")
    texture.wrapS = THREE.RepeatWrapping;
   
    let outMaterial = new THREE.MeshPhongMaterial({
        color: 0x7dffeb,
        //map: texture,
        side: THREE.FrontSide
    });
    let texture2 = app.getLoadedResources().getTexture("innerwall")
    texture2.wrapS = THREE.RepeatWrapping;
   
    let innerMaterial = new THREE.MeshPhongMaterial({
        color: 0x7dffeb,
        map: texture2,
        side: THREE.FrontSide
    });
    
    let nodeOutMaterial = new THREE.MeshPhongMaterial({
        color: 0x7dffeb,
        side: THREE.FrontSide
    });
    // 从图中获取三维坐标数据，也可以直接给坐标
    let mapid = env.mapId
    let style = await app.svc.createStyle({
        backcolor: 0,
    }, mapid, env.version)
    let tubeDatas = [];
    let query = await app.svc.conditionQueryFeature({
        mapid: mapid,
        version: env.version,
        layer: style.stylename,
        geom: true,
        condition: `name='2' or name='4'`,// 查找有高程值的多段线和三维多段线
        fields: "objectid,points,elevation",
        limit: 100000
    });
    let results = query.result;
    let box3d = new THREE.Box3();
    let allPts = []
    
    let lineDatas = []
    if (results && results.length > 0) {
        for(let n = 0; n < results.length; n++) {
            let linePoints =  results[n].points.split(";").map(p => vjmap3d.GeoPoint.fromString(p));
            // @ts-ignore
            linePoints = linePoints.map(p => vjmap3d.toVector3([p.x, p.z ?? results[n].elevation ?? 0, p.y]));
    
            lineDatas.push(linePoints)
    
             // 记录下所有点坐标，用来计算范围
            allPts.push(...linePoints)
    
            tubeDatas.push({
                paths: linePoints,
                name:  results[n].objectid
            })
        }
    }
    
    
    // 获取数据范围
    box3d.setFromPoints(allPts)
    
    // 计算中心点
    let center = box3d.min.clone().add(box3d.max).multiplyScalar(0.5);
    
    // 因为业务数据有可能坐标很大或很小，所以对整个应用根据坐标范围对坐标进行一个平移和缩放
    app.centerOrigin = new THREE.Vector3(center.x, box3d.min.y, center.z);
    // 根据最大距离，缩放至宽度为200左右
    let dist = Math.max(box3d.max.x - box3d.min.x, box3d.max.z - box3d.min.z);
    app.scaleOrigin = 200 / dist;
    
    // 根据设置的平移和缩放量，重新计算下坐标
    for(let p of tubeDatas ) {
        p.paths = p.paths.map((t: any) => vjmap3d.toWorld(t.toArray()).toArray())
    }
    
    let tubeEntity: PathTubeEntities;
    let cancelActionCb: any;
    const createTubeEntity = (data: any, sect?: any) => {
        if (tubeEntity) {
            // 如果之前实体创建了，先删除
            tubeEntity.entity.remove();
            //@ts-ignore
            tubeEntity = null;
        }
        if (cancelActionCb) {
            // 如果之前设置了纹理流动,先取消了
            cancelActionCb()
            cancelActionCb = null;
        }
        let opts = {
            data: data,
           
            nodeRadius: 0.5,
            innerSideMaterial: innerMaterial,
            outerMaterial: outMaterial,
            nodeOuterMaterial: nodeOutMaterial,
            sect: sect ?? {
                shape: "arch",
                rectWidth: 1,
                rectHeight: 0.5
            },
            /** 建立拓扑关系策略（默认nodeIntersect） nodeIntersect 一条管道的始末节点与另一条相交时，自动把另一条拆成多段建立拓扑。nodeEqual 一条管道的始末节点与另一条管道的始末节点相等时建立拓扑，不会自动拆分 */
            topoStrategy: "nodeIntersect"
        }
        // @ts-ignore
        let pathTube = new vjmap3d.PathTubeEntities(opts);
        pathTube.addTo(app);
        // 
        for(let n = 0; n < pathTube.entity.childrens.length; n++) {
            let ent = pathTube.entity.childrens[n];
            ent.add(vjmap3d.EventModule, {
                clickHighlight: true,
                highlightOpacity: 0.2,
                hoverSelect: true,
                // @ts-ignore
                hoverHtmlText: ent.node.isNode ? 
               `节点：关联${ent.node.userData.dataIndexs} 条路径`:
               pathTube.data[ent.node.userData.dataIndex].name,
                popupOptions: {
                    anchor: "bottom"
                }
            });
        }
    
        tubeEntity = pathTube;
    }
    
    createTubeEntity(tubeDatas)

  
    let actionCb: any;
    const showHideFlowTexture = (bShow) => {
        if (actionCb) {
            actionCb();
            actionCb = null;
        }
        if (bShow) {
            outMaterial.map = texture;
            actionCb = tubeEntity.entity.addAction(() => {
                texture.offset.x -= 0.02;
            })
        } else {
            outMaterial.map = null;
        }
        outMaterial.needsUpdate = true
    }
    
    return {
        tubeDatas,
        createTubeEntity,
        outerTexture: texture,
        innerTexture: texture2,
        // @ts-ignore
        tubeEntity,
        showHideFlowTexture
    }
}

export const createSymbol = (app: App, parent: vjmap3d.Entity, co: [number, number, number], personId: number, image: any) => {
    //let texture = app.getLoadedResources().getTexture("man")
    let spriteMarker = new SpriteMarkerEntity(
    {
        position: co, // 位置 
        sizeAttenuation: false, // 固定像素大小，不随相机变化
        anchorX: "center",  // x对齐方式
        anchorY: "bottom", // y对齐方式
        renderTexture: {
            autoCanvasSize: false,
            canvasWidth: 60, // 像素宽，这里是根据底图的像素宽高定的
            canvasHeight: 100, // 像素高，这里是根据底图的像素宽高定的
            sharedCanvas: true,
            elements: [
                new vjmap3d.render2d.Image({
                    style: {
                        x: 0,
                        y: 0,
                        image: image,
                        width: 60, // 像素宽，这里是图片像素宽高定的
                        height: 100 // 像素高，这里是图片像素宽高定的
                    }
                }),
                new vjmap3d.render2d.Text({
                    style: {
                        x: 30,
                        y: 15,
                        text: '人员' + personId,
                        fill: "#0ff",
                        font: '16px Arial',
                        verticalAlign: "top",
                        align: "center"
                    }
                })
            ]
        }
    });
    spriteMarker.addTo(parent, app)

    spriteMarker.add(vjmap3d.EventModule, {
        hoverSelect: true, // 悬浮时选中
        clickCallback: (ent, isClick, object) => {
            if (isClick) {
                app.data.showPersonDetail = true;
                app.data.personId = personId;
                app.data.personName = '人员' + personId;
                app.data.personRoutes = spriteMarker.data.routes;
                
                if (!ent.data.waveMesh) {
                    // @ts-ignore
                    ent.data.waveMesh = createShaderWave(spriteMarker.SpriteMarker, new THREE.Vector3(0, 0, 0), app)
                }
            } else {
                if (ent.data.waveMesh) {
                    // 没有选中时，删除之前的
                    ent.data.waveMesh.parent.remove(ent.data.waveMesh);
                    delete ent.data.waveMesh
                }
                if (object == null) {
                    // 如果没有选择的
                    app.data.showPersonDetail = false;
                }
            }
           
        }
    });
    return spriteMarker
}


export const initPersonMove = async (app: App, tubeEntity: PathTubeEntities) => {
    let mock = mockData(tubeEntity)
    // 第一次时创建
    let personMarkerGroupEntity = new vjmap3d.Entity();
    personMarkerGroupEntity.addTo(app);

    let spriteMarkers: SpriteMarkerEntity[] = [];
    let data = mock.getData();
    let image = await vjmap3d.loadImage("textures/manname.png")
    for(let n= 0; n < data.length; n++) {
        spriteMarkers.push(createSymbol(app, personMarkerGroupEntity, data[n].point, n + 1, image));
    }

    const move = async () => {
        let nextData = mock.getData();
     
        // 记录下历史数据用于轨迹回放
        for(let n = 0; n < nextData.length; n++) {
            let routes = nextData[n].route
            if (!spriteMarkers[n].data.routes) {
                spriteMarkers[n].data.routes = [...routes]
            } else {
                // 第一个点的和之前的重复了，不要
                for(let k = 1; k < routes.length; k++) {
                    spriteMarkers[n].data.routes.push(routes[k])
                }
            }
            
        }

        // 行走动画
        await animationAsync({
            duration: 3000,
            onProgress: (target, key, start, end, alpha, reversed) => {
                for(let n = 0; n < nextData.length; n++) {
                    let routes = nextData[n].route.map((r: any) => r.posTop.toArray())
                    let pts = interpolatePointsByRatio(routes, alpha);
                    if (pts.length > 0) {
                        let co = pts[pts.length - 1];
                        // @ts-ignore
                        spriteMarkers[n].SpriteMarker.position.copy(toVector3(co))
                    } else {
                        spriteMarkers[n].visible = false;
                    }
                }
            }
        })
     
    }
    
    let isStop = false;
    
    const run = async () => {
        while(!isStop) {
            await move()
        }
    }
    run();

    app.data.personMarkerGroupEntity = personMarkerGroupEntity;
    app.data.tubeEntity = tubeEntity;
    return {
        personMarkerGroupEntity
    }
}


